package com.qf.aop.aspect;

import com.qf.aop.async.AsyncTaskFactory;
import com.qf.core.provider.LoginUserProvider;
import com.qf.core.thread.ThreadPoolManager;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @Author: sin
 * @Date: 2025/5/4 14:39
 * @Description: 操作日志记录处理
 **/
@Aspect
@Component
@Slf4j
public class ApiOperationLogAspect {

    @Autowired
    private AsyncTaskFactory asyncTaskFactory;

    @Autowired
    private LoginUserProvider loginUserProvider;
    /**
     * 处理完请求后执行
     *
     * @param joinPoint 切点
     */
    @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
    public void doAfterReturning(JoinPoint joinPoint, ApiOperationLog controllerLog, Object jsonResult) {
        handleLog(joinPoint, controllerLog, null, jsonResult);
    }

    /**
     * 拦截异常操作
     *
     * @param joinPoint 切点
     * @param e 异常
     */
    @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, ApiOperationLog controllerLog, Exception e) {
        handleLog(joinPoint, controllerLog, e, null);
    }

    protected void handleLog(final JoinPoint joinPoint, ApiOperationLog accessLog, final Exception e, Object jsonResult) {
        try {
            OperationLogModel operationLog = new OperationLogModel();
            operationLog.fillOperatorInfo(loginUserProvider.getUsername(), loginUserProvider.getUserId());
            operationLog.fillRequestInfo(joinPoint, accessLog, jsonResult);
            operationLog.fillStatus(e);
            operationLog.fillAccessLogInfo(joinPoint,accessLog);
            ThreadPoolManager.execute(asyncTaskFactory.recordOperationLog(operationLog));
        } catch (Exception exp) {
            log.error("写入操作日志失败");
            // 切面异常不能被全局捕获到，这块拿到异常之后继续往上抛
            throw exp;
        }
    }
}
